package com.farm.material.service.impl;

import com.farm.material.domain.Categray;
import com.farm.material.domain.Categrayfile;
import com.farm.material.domain.Categraytag;
import com.farm.material.domain.ex.JsTreeNode;
import com.farm.core.time.TimeTool;
import com.farm.file.FarmFileServiceInter;
import com.farm.file.domain.ex.FileView;
import com.farm.file.service.VisitServiceInter.OpModel;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.ss.formula.functions.T;

import com.farm.material.dao.CategrayDaoInter;
import com.farm.material.dao.CategrayfileDaoInter;
import com.farm.material.service.CategrayServiceInter;
import com.farm.util.web.FarmFormatUnits;
import com.farm.core.sql.query.DBRule;
import com.farm.core.sql.query.DBRuleList;
import com.farm.core.sql.query.DBSort;
import com.farm.core.sql.query.DataQuery;
import com.farm.core.sql.result.DataResult;
import com.farm.core.sql.result.ResultsHandle;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileNotFoundException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import com.farm.core.auth.domain.LoginUser;


@SuppressWarnings("restriction")
@Service
public class CategrayServiceImpl implements CategrayServiceInter {
	@Resource
	private CategrayDaoInter categrayDaoImpl;
	@Resource
	private FarmFileServiceInter farmFileServiceImpl;
	@Resource
	private CategrayfileDaoInter categrayfileDaoImpl;
	private static final Logger log = Logger.getLogger(CategrayServiceImpl.class);

	@Override
	@Transactional
	public void moveTreeNode(String ids, String targetId, LoginUser currentUser) {
		String[] idArray = ids.split(",");
		Categray target = getCategrayEntity(targetId);
		for (int i = 0; i < idArray.length; i++) {
			// 移动节点
			Categray node = getCategrayEntity(idArray[i]);
			if (target != null && target.getTreecode().indexOf(node.getTreecode()) >= 0) {
				throw new RuntimeException("不能够移动到其子节点下!");
			}
			if (target == null) {
				node.setParentid("NONE");
			} else {
				node.setParentid(targetId);
			}
			categrayDaoImpl.editEntity(node);
			// 构造所有树TREECODE
			List<Categray> list = categrayDaoImpl.getAllSubNodes(idArray[i]);
			for (Categray org : list) {
				initTreeCode(org.getId());
			}
		}
	}

	@Override
	@Transactional
	public Categray insertCategrayEntity(Categray entity, LoginUser user) {
		entity.setCuser(user.getId());
		entity.setCtime(TimeTool.getTimeDate14());
		entity.setEuser(user.getId());
		entity.setEtime(TimeTool.getTimeDate14());
		entity.setPstate("1");
		entity.setAllnum(0);
		entity.setCnum(0);
		entity.setClayout("NONE");
		entity.setCsort("NONE");
		entity.setType("0");
		entity.setCmodel("NONE");
		entity.setTreecode("NONE");
		if (StringUtils.isBlank(entity.getParentid())) {
			entity.setParentid("NONE");
		}
		entity = categrayDaoImpl.insertEntity(entity);
		initTreeCode(entity.getId());
		return entity;
	}

	
	private void initTreeCode(String treeNodeId) {
		Categray node = getCategrayEntity(treeNodeId);
		if (node.getParentid().equals("NONE")) {
			node.setTreecode(node.getId());
		} else {
			node.setTreecode(categrayDaoImpl.getEntity(node.getParentid()).getTreecode() + node.getId());
		}
		categrayDaoImpl.editEntity(node);
	}

	@Override
	@Transactional
	public Categray editCategrayEntity(Categray entity, LoginUser user) {
		Categray entity2 = categrayDaoImpl.getEntity(entity.getId());
		// entity2.setEuser(user.getId());
		// entity2.setEusername(user.getName());
		// entity2.setEtime(TimeTool.getTimeDate14());
		entity2.setPcontent(entity.getPcontent());
		entity2.setPstate(entity.getPstate());
		// entity2.setEuser(entity.getEuser());
		// entity2.setCuser(entity.getCuser());
		// entity2.setEtime(entity.getEtime());
		// entity2.setCtime(entity.getCtime());
		// entity2.setId(entity.getId());
		entity2.setSort(entity.getSort());
		// entity2.setParentid(entity.getParentid());
		entity2.setName(entity.getName());
		// entity2.setTreecode(entity.getTreecode());
		// entity2.setType(entity.getType());
		// entity2.setCsort(entity.getCsort());
		// entity2.setClayout(entity.getClayout());
		// entity2.setCmodel(entity.getCmodel());
		// entity2.setCnum(entity.getCnum());
		// entity2.setAllnum(entity.getAllnum());
		categrayDaoImpl.editEntity(entity2);
		return entity2;
	}

	@Override
	@Transactional
	public void deleteCategrayEntity(String id, LoginUser user) {
		if (categrayDaoImpl.selectEntitys(DBRule.addRule(new ArrayList<DBRule>(), "parentid", id, "=")).size() > 0) {
			throw new RuntimeException("不能删除该节点，请先删除其子节点");
		}
		Categray type = categrayDaoImpl.getEntity(id);
		// 处理中间表
		categrayDaoImpl.deleteEntity(type);
	}

	@Override
	@Transactional
	public Categray getCategrayEntity(String id) {
		// TODO 自动生成代码,修改后请去除本注释
		if (id == null) {
			return null;
		}
		return categrayDaoImpl.getEntity(id);
	}

	@Override
	@Transactional
	public DataQuery createCategraySimpleQuery(DataQuery query) {
		// TODO 自动生成代码,修改后请去除本注释
		DataQuery dbQuery = DataQuery.init(query, "WML_C_CATEGRAY",
				"ID,PCONTENT,PSTATE,EUSER,CUSER,ETIME,CTIME,SORT,PARENTID,NAME,TREECODE,TYPE,CSORT,CLAYOUT,CMODEL,CNUM,ALLNUM");
		return dbQuery;
	}

	
	private Set<String> getIdsByLikeName(String name) throws SQLException {
		Set<String> set = new HashSet<String>();
		DataQuery dbQuery = DataQuery.getInstance(1,
				"ID,PCONTENT,PSTATE,EUSER,CUSER,ETIME,CTIME,SORT,PARENTID,NAME,TREECODE,TYPE,CSORT,CLAYOUT,CMODEL,CNUM,ALLNUM",
				"WML_C_CATEGRAY");
		dbQuery.setPagesize(10000);
		dbQuery.setNoCount();
		dbQuery.addRule(new DBRule("NAME", name, "like"));
		dbQuery.search().getResultList().forEach(t -> {
			set.addAll(FarmFormatUnits.SplitStringByLen(t.get("TREECODE").toString(), 32));
		});
		return set;
	}

	@Override
	@Transactional
	public List<JsTreeNode> getAllCategrays(String name, LoginUser currentUser) {
		try {
			Set<String> ableids = StringUtils.isNotBlank(name) ? getIdsByLikeName(name) : null;
			DataQuery dbQuery = DataQuery.getInstance(1,
					"ID,PCONTENT,PSTATE,EUSER,CUSER,ETIME,CTIME,SORT,PARENTID,NAME,TREECODE,TYPE,CSORT,CLAYOUT,CMODEL,CNUM,ALLNUM",
					"WML_C_CATEGRAY");
			dbQuery.setPagesize(10000);
			dbQuery.addRule(new DBRule("PSTATE", "1", "="));
			dbQuery.setNoCount();
			// 查询、排序、转换为JsTreeNode
			List<JsTreeNode> list = dbQuery.search().getResultList().stream().filter(t -> {
				return ableids != null ? ableids.contains(t.get("ID")) : true;
			}).sorted((o1, o2) -> {
				return o1.get("TREECODE").toString().length() == o2.get("TREECODE").toString().length()
						? (int) o1.get("SORT") - (int) o2.get("SORT")
						: o1.get("TREECODE").toString().length() - o2.get("TREECODE").toString().length();
			}

			).map((Map<String, Object> t) -> new JsTreeNode(t.get("ID").toString(), t.get("PARENTID").toString(),
					t.get("NAME").toString(), (int) t.get("ALLNUM"))).collect(Collectors.toList());
			// 组装
			List<JsTreeNode> baclist = new ArrayList<JsTreeNode>();
			{
				Map<String, JsTreeNode> dics = new HashMap<String, JsTreeNode>();
				for (JsTreeNode node : list) {
					dics.put(node.getId(), node);
					if (node.getParentid().equals("NONE")) {
						baclist.add(node);
					} else {
						JsTreeNode parent = dics.get(node.getParentid());
						if (parent != null) {
							if (parent.getChildren() == null) {
								parent.setChildren(new ArrayList<JsTreeNode>());
							}
							parent.getChildren().add(node);
						}
					}
				}
			}
			return baclist;
		} catch (SQLException e) {
			e.printStackTrace();
			List<JsTreeNode> error = new ArrayList<JsTreeNode>();
			error.add(new JsTreeNode("1", e.getMessage(), 0));
			return error;
		}
	}

	@Override
	@Transactional
	public void bindFile(String categrayid, String fileid) {
		try {
			categrayfileDaoImpl.deleteEntitys(DBRuleList.getInstance().add(new DBRule("FILEID", fileid, "=")).toList());
			Categrayfile entity = new Categrayfile();
			entity.setFileid(fileid);
			entity.setCategrayid(categrayid);
			entity.setPstate("1");
			categrayfileDaoImpl.insertEntity(entity);
			farmFileServiceImpl.submitFile(fileid);
		} catch (FileNotFoundException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	@Transactional
	public List<FileView> getFiles(String categrayid, Integer page) {
		DataQuery dbQuery = DataQuery.getInstance(1,
				"B.TITLE AS TITLE,B.EXNAME AS EXNAME,B.FILESIZE AS FILESIZE,B.ID AS FILEID,B.CTIME AS CTIME,A.ID AS APPID",
				"WML_C_CATEGRAYFILE A LEFT JOIN WML_F_FILE B ON A.FILEID=B.ID");
		dbQuery.setPagesize(500);
		if (page == null || page == 0) {
			page = 1;
		}
		dbQuery.setCurrentPage(page);
		dbQuery.setNoCount();
		dbQuery.addRule(new DBRule("A.CATEGRAYID", categrayid, "="));
		dbQuery.addRule(new DBRule("A.PSTATE", "1", "="));
		List<FileView> list = null;
		try {

			DataResult dr = dbQuery.search();
			list = dr.getResultList().stream()
					.map(t -> new FileView((String) t.get("TITLE"), (Integer) t.get("FILESIZE"),
							(String) t.get("FILEID"), (String) t.get("APPID"), (String) t.get("EXNAME"),
							(String) t.get("CTIME")))
					.collect(Collectors.toList());
			Categray categray = categrayDaoImpl.getEntity(categrayid);
			if (categray != null) {
				categray.setCnum(dr.getTotalSize());
				categray.setAllnum(categrayDaoImpl.getAllsubFileNum(categrayid));
				categrayDaoImpl.editEntity(categray);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return list;
	}

	@Override
	@Transactional
	public List<FileView> getCategrays(String categrayid) {
		DataQuery dbQuery = DataQuery.getInstance(1,
				"ID,PCONTENT,PSTATE,EUSER,CUSER,ETIME,CTIME,SORT,PARENTID,NAME,TREECODE,TYPE,CSORT,CLAYOUT,CMODEL,CNUM,ALLNUM",
				"WML_C_CATEGRAY");
		dbQuery.setPagesize(10000);
		dbQuery.setNoCount();
		dbQuery.addRule(new DBRule("PARENTID", categrayid, "like"));
		dbQuery.addRule(new DBRule("PSTATE", "1", "like"));
		List<FileView> list = null;
		try {
			list = dbQuery.search().getResultList().stream()
					.map(t -> new FileView((String) t.get("NAME"), (String) t.get("ID"), "WML_DIR",
							(String) t.get("CTIME"), (int) t.get("CNUM"), (int) t.get("ALLNUM")))
					.collect(Collectors.toList());
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return list;
	}

	@Override
	@Transactional
	public List<FileView> getVlogFiles(LoginUser currentUser, OpModel model, Integer page) {
		DataQuery dbQuery = DataQuery.getInstance(1,
				"B.TITLE AS TITLE,B.EXNAME AS EXNAME,B.FILESIZE AS FILESIZE,B.ID AS FILEID,B.CTIME AS CTIME,A.ID AS APPID",
				"WML_F_VISITLOGS A LEFT JOIN WML_F_FILE B ON A.APPID=B.ID");
		dbQuery.setPagesize(500);
		if (page == null || page == 0) {
			page = 1;
		}
		dbQuery.setCurrentPage(page);
		dbQuery.setNoCount();
		dbQuery.addRule(new DBRule("A.CUSER", currentUser.getId(), "="));
		dbQuery.addRule(new DBRule("A.TYPE", model.getType(), "="));
		dbQuery.addSqlRule(" AND B.ID IS NOT NULL");
		dbQuery.addSort(new DBSort("CTIME", "DESC"));
		List<FileView> list = null;
		try {
			DataResult dr = dbQuery.search();
			list = dr.getResultList().stream().map(t -> {
				return new FileView((String) t.get("TITLE"), (Integer) t.get("FILESIZE"), (String) t.get("FILEID"),
						model.name() + (String) t.get("APPID"), (String) t.get("EXNAME"), (String) t.get("CTIME"));
			}).collect(Collectors.toList());
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return list;
	}

	@Override
	@Transactional
	public List<FileView> getVlogCategrays(LoginUser currentUser, OpModel model, Integer page) {
		DataQuery dbQuery = DataQuery.getInstance(1, "B.ID AS ID,B.NAME AS NAME,B.CTIME AS CTIME,CNUM,ALLNUM",
				"WML_F_VISITLOGS A LEFT JOIN WML_C_CATEGRAY B ON A.APPID=B.ID");
		dbQuery.setPagesize(500);
		if (page == null || page == 0) {
			page = 1;
		}
		dbQuery.setCurrentPage(page);
		dbQuery.setNoCount();
		dbQuery.addRule(new DBRule("A.CUSER", currentUser.getId(), "="));
		dbQuery.addRule(new DBRule("A.TYPE", model.getType(), "="));
		dbQuery.addSqlRule(" AND B.ID IS NOT NULL");
		dbQuery.addSort(new DBSort("CTIME", "DESC"));
		List<FileView> list = null;
		try {
			list = dbQuery.search().getResultList().stream()
					.map(t -> new FileView((String) t.get("NAME"), (String) t.get("ID"), "WML_DIR",
							(String) t.get("CTIME"), (int) t.get("CNUM"), (int) t.get("ALLNUM")))
					.collect(Collectors.toList());
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return list;
	}

	@Override
	@Transactional
	public List<FileView> getRecycleFiles(LoginUser currentUser, Integer page) {
		DataQuery dbQuery = DataQuery.getInstance(1,
				"B.TITLE AS TITLE,B.EXNAME AS EXNAME,B.FILESIZE AS FILESIZE,B.ID AS FILEID,B.CTIME AS CTIME,A.ID AS APPID",
				"WML_C_CATEGRAYFILE A LEFT JOIN WML_F_FILE B ON A.FILEID=B.ID");
		dbQuery.setPagesize(500);
		if (page == null || page == 0) {
			page = 1;
		}
		dbQuery.setCurrentPage(page);
		dbQuery.setNoCount();
		dbQuery.addRule(new DBRule("A.PSTATE", "0", "="));
		dbQuery.addRule(new DBRule("A.DUSER", currentUser.getId(), "="));
		List<FileView> list = null;
		try {
			DataResult dr = dbQuery.search();
			list = dr.getResultList().stream()
					.map(t -> new FileView((String) t.get("TITLE"), (Integer) t.get("FILESIZE"),
							(String) t.get("FILEID"), (String) t.get("APPID"), (String) t.get("EXNAME"),
							(String) t.get("CTIME")))
					.collect(Collectors.toList());
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return list;
	}
}
